package com.atguigu.controller;

import com.atguigu.client.OrderFeignClient;
import com.atguigu.client.UserFeignClient;
import com.atguigu.constant.MqConst;
import com.atguigu.constant.RedisConst;
import com.atguigu.entity.*;
import com.atguigu.result.RetVal;
import com.atguigu.result.RetValCodeEnum;
import com.atguigu.service.SeckillProductService;
import com.atguigu.util.AuthContextHolder;
import com.atguigu.util.MD5;
import com.atguigu.utils.DateUtil;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@RequestMapping("/seckill")
@RestController
public class SeckillController {
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    SeckillProductService seckillProductService;
    @Autowired
    RabbitTemplate rabbitTemplate;
    @Autowired
    UserFeignClient userFeignClient;
    @Autowired
    OrderFeignClient orderFeignClient;
    //1.查询所有秒杀商品
    @GetMapping("/queryAllSeckillProduct")
    public RetVal queryAllSeckillProduct(){
        List<SeckillProduct> seckillProductList = redisTemplate.boundHashOps(RedisConst.SECKILL_PRODUCT).values();
        return RetVal.ok(seckillProductList);
    }

    //2.根据skuId 获取秒杀对象的详情页
    @GetMapping("/getSeckillProductBySkuId/{skuId}")
    public RetVal getSeckillProductBySkuId(@PathVariable Long skuId){
        SeckillProduct seckillProduct = seckillProductService.getSeckillProductFromRedis(skuId);
        return RetVal.ok(seckillProduct);
    }

    //3.生成抢购码，防止用户直接跳过商品详情页面进入秒杀
    @GetMapping("/generateSeckillCode/{skuId}")
    public RetVal generateSeckillCode(HttpServletRequest request, @PathVariable Long skuId){
        String userId = AuthContextHolder.getUserId(request);
        if (!StringUtils.isEmpty(userId)){
            //从缓存中查询该秒杀商品
            SeckillProduct seckillProduct =seckillProductService.getSeckillProductFromRedis(skuId);
            //判断时间是否在这个时间段内
            Date currentTime = new Date();
            //当前时间如果在秒杀时间范围内 则生成下单码
            if (DateUtil.dateCompare(seckillProduct.getStartTime(),currentTime) &&
                    DateUtil.dateCompare(currentTime,seckillProduct.getEndTime())){
                //生成规则 将用户Id使用md5加密
                String seckillCode = MD5.encrypt(userId);
                return RetVal.ok(seckillCode);
            }
        }
        return RetVal.fail().message("获取下单码失败");
    }

    //4.秒杀预下单
    @PostMapping("/prepareSeckill/{skuId}")
    public RetVal prepareSeckill(@PathVariable Long skuId,String seckillCode,HttpServletRequest request){
        String userId = AuthContextHolder.getUserId(request);
        //下单码不匹配的时候报异常
        if (!MD5.encrypt(userId).equals(seckillCode)){
            return RetVal.build(null, RetValCodeEnum.SECKILL_ILLEGAL);
        }
        //没有获取到状态位信息时
        String state = (String)redisTemplate.opsForValue().get(RedisConst.SECKILL_STATE_PREFIX+skuId.toString());
        if(StringUtils.isEmpty(state)){
            return RetVal.build(null, RetValCodeEnum.SECKILL_ILLEGAL);
        }
        if (RedisConst.CAN_SECKILL.equals(state)){
            UserSeckillSkuInfo userSeckillSkuInfo = new UserSeckillSkuInfo();
            //哪个用户购买了哪个商品
            userSeckillSkuInfo.setUserId(userId);
            userSeckillSkuInfo.setSkuId(skuId);
            rabbitTemplate.convertAndSend(MqConst.PREPARE_SECKILL_EXCHANGE,MqConst.PREPARE_SECKILL_ROUTE_KEY, userSeckillSkuInfo);
        }else {
            //秒杀商品已售完
            return RetVal.build(null, RetValCodeEnum.SECKILL_FINISH);
        }
        return RetVal.ok();
    }

    //5.是否具有抢单的资格
    @GetMapping("/hasQualified/{skuId}")
    public RetVal hasQualified(@PathVariable Long skuId,HttpServletRequest request){
        String userId = AuthContextHolder.getUserId(request);
        return seckillProductService.hasQualified(skuId,userId);
    }


    //6.秒杀商品确认信息
    @GetMapping("/seckillConfirm")
    public RetVal seckillConfirm(HttpServletRequest request){
        String userId = AuthContextHolder.getUserId(request);
        //1.秒杀到的预售商品订单信息
        PrepareSeckillOrder prepareSeckillOrder = (PrepareSeckillOrder) redisTemplate.boundHashOps(RedisConst.PREPARE_SECKILL_USERID_ORDER).get(userId);
        if (prepareSeckillOrder ==null){
            return RetVal.fail().message("非法操作");
        }
        //2.获取用户收货地址列表
        List<UserAddress> userAddressList = userFeignClient.queryAddressByUserId(userId);
        //3.用户秒杀到哪个商品
        SeckillProduct seckillProduct = prepareSeckillOrder.getSeckillProduct();
        //4.创建一个秒杀订单明细
        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setSkuId(seckillProduct.getSkuId());
        orderDetail.setSkuName(seckillProduct.getSkuName());
        orderDetail.setImgUrl(seckillProduct.getSkuDefaultImg());
        orderDetail.setSkuNum(prepareSeckillOrder.getBuyNum()+"");
        orderDetail.setOrderPrice(seckillProduct.getCostPrice());
        //由于页面要求传递一个集合 其实在这里我们只有一个商品
        List<OrderDetail> orderDetailList = new ArrayList<>();
        orderDetailList.add(orderDetail);
        //把这些数据封装到一个map中
        Map<String,Object> result = new HashMap<>();
        result.put("userAddressList",userAddressList);
        result.put("orderDetailList",orderDetailList);
        result.put("totalMoney",seckillProduct.getCostPrice());
        return RetVal.ok(result);
    }


    //7.提交秒杀订单
    @PostMapping("/submitSecKillOrder")
    public RetVal submitSecKillOrder(@RequestBody OrderInfo orderInfo,HttpServletRequest request){
        String userId = AuthContextHolder.getUserId(request);
        orderInfo.setUserId(Long.parseLong(userId));
        //判断用户是否有预下单
        PrepareSeckillOrder prepareSeckillOrder = (PrepareSeckillOrder) redisTemplate.boundHashOps(RedisConst.PREPARE_SECKILL_USERID_ORDER).get(userId);
        if (prepareSeckillOrder ==null){
            return RetVal.fail().message("非法操作！");
        }
        //远程调用保存秒杀订单
        Long orderId = orderFeignClient.saveSeckillOrder(orderInfo);
        if (orderId ==null){
            return RetVal.fail().message("下单失败！");
        }
        //根据userId删除预订单
        redisTemplate.boundHashOps(RedisConst.PREPARE_SECKILL_USERID_ORDER).delete(userId);
        //为了让用户只能购买一次 将秒杀的商品数据保存到缓存
        redisTemplate.boundHashOps(RedisConst.BOUGHT_SECKILL_USER_ORDER).put(userId, orderId.toString());
        return RetVal.ok(orderId);
    }




}
